package dao

import (
	"context"
	"errors"
	"fmt"
	"ruoyi-go-echo-ddd/internal/domain/model"
	"ruoyi-go-echo-ddd/internal/infrastructure/http/request"
	"ruoyi-go-echo-ddd/internal/infrastructure/persistence/config"
	"ruoyi-go-echo-ddd/internal/infrastructure/utils"

	"github.com/rs/zerolog"
	"gorm.io/gorm"
)

// SysUserRoleDaoImpl 用户角色信息Dao实现结构体
type SysUserRoleDaoImpl struct {
	db config.PrimaryDB
}

// NewSysUserRoleDaoImpl 用户角色信息Dao实现创建
func NewSysUserRoleDaoImpl(db config.PrimaryDB) *SysUserRoleDaoImpl {
	return &SysUserRoleDaoImpl{
		db: db,
	}
}

func (orm *SysUserRoleDaoImpl) Insert(ctx context.Context, sysUserRole *model.SysUserRole) (*model.SysUserRole, error) {
	if err := orm.db.WithContext(ctx).Create(&sysUserRole).Error; err != nil {
		return nil, errors.New("用户角色信息新增失败")
	}
	// 如果这里边有使用钩子函数，那么这里需要重新查询而不是直接返回sysUserRole
	sysUserRole, err := orm.SelectById(ctx, sysUserRole.RoleId)
	if err != nil {
		return nil, errors.New("用户角色信息新增失败")
	}
	return sysUserRole, nil
}

func (orm *SysUserRoleDaoImpl) Update(ctx context.Context, sysUserRole *model.SysUserRole) (int64, error) {
	result := orm.db.WithContext(ctx).Model(&model.SysUserRole{}).
		Where("id = ?", sysUserRole.RoleId).
		Omit("id").
		Updates(&sysUserRole)
	if result.Error != nil {
		return 0, errors.New("用户角色信息修改失败")
	}

	return result.RowsAffected, nil
}

func (orm *SysUserRoleDaoImpl) BatchInsert(ctx context.Context, list []*model.SysUserRole) ([]int64, error) {
	if len(list) <= 0 {
		return nil, errors.New("用户角色信息批量新增参数验证失败")
	}

	result := orm.db.WithContext(ctx).CreateInBatches(list, 50)
	if result.Error != nil {
		return nil, errors.New("用户角色信息批量新增失败")
	}

	var ids []int64
	for _, item := range list {
		ids = append(ids, item.RoleId)
	}

	return ids, nil
}

func (orm *SysUserRoleDaoImpl) SelectById(ctx context.Context, id int64) (*model.SysUserRole, error) {
	var sysUserRole *model.SysUserRole
	// 主键为id的时候First(&sysUserRole, id)默认使用主键ID查询
	if err := orm.db.WithContext(ctx).Model(&model.SysUserRole{}).First(&sysUserRole, id).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, errors.New("用户角色信息未找到")
		}
		return nil, errors.New("用户角色信息查询失败")
	}
	return sysUserRole, nil
}

func (orm *SysUserRoleDaoImpl) SelectPage(ctx context.Context, param *request.CommonPageParam) ([]*model.SysUserRole, int64, int64, error) {
	pageParam := utils.InitPageParam(param.Page, param.Size)

	// 初始化 GORM 查询
	db := orm.db.WithContext(ctx).Model(&model.SysUserRole{})
	// 查询总记录数
	var total int64
	if err := db.Count(&total).Error; err != nil {
		return nil, 0, 0, errors.New("获取用户角色信息总记录数失败")
	}

	// 查询用户列表
	var list []*model.SysUserRole
	if err := utils.SetOrder(db, param.Column, param.Order).
		Offset(int(pageParam.Offset)).Limit(int(pageParam.Size)).
		Find(&list).Error; err != nil {
		return nil, 0, 0, errors.New("获取用户角色信息列表失败")
	}

	return list, total, utils.CalcTotalPage(total, param.Size), nil
}

func (orm *SysUserRoleDaoImpl) BatchDelete(ctx context.Context, ids []any) (int64, error) {
	if len(ids) <= 0 {
		return 0, errors.New("用户角色信息批量删除参数验证失败")
	}
	result := orm.db.WithContext(ctx).Model(&model.SysUserRole{}).Where("id IN (?)", ids).Delete(nil)
	if result.Error != nil {
		return 0, errors.New("批量删除失败")
	}
	return result.RowsAffected, nil
}

func (orm *SysUserRoleDaoImpl) DeleteByUserId(ctx context.Context, userId int64) (int64, error) {
	result := orm.db.WithContext(ctx).Model(&model.SysUserRole{}).Where("user_id = ?", userId).Delete(nil)
	if result.Error != nil {
		zerolog.DefaultContextLogger.Error().Err(result.Error).Msgf("通过用户ID===%d删除绑定角色失败===", userId)
		return 0, fmt.Errorf("通过用户ID===%d删除绑定角色失败", userId)
	}
	zerolog.DefaultContextLogger.Info().Msgf("用户角色信息批量删除成功执行条数===%d", result.RowsAffected)
	return result.RowsAffected, nil
}

func (orm *SysUserRoleDaoImpl) DeleteByUserIdList(ctx context.Context, userIds []int64) (int64, error) {
	result := orm.db.WithContext(ctx).Model(&model.SysUserRole{}).Where("user_id IN ?", userIds).Delete(nil)
	if result.Error != nil {
		zerolog.DefaultContextLogger.Error().Err(result.Error).Msgf("通过用户ID===%v删除绑定角色失败===", userIds)
		return 0, fmt.Errorf("通过用户ID===%v删除绑定角色失败,%w", userIds, result.Error)
	}
	zerolog.DefaultContextLogger.Info().Msgf("用户角色信息批量删除成功执行条数===%d", result.RowsAffected)
	return result.RowsAffected, nil
}
